#include "save.h"

namespace sp::Image::Save{

void registe_save(){
    save::registe();
}

save::save(std::vector<std::string> v){ // std::string path, int fps, int width, int height
    assert(v.size() == 4);
    name = "save";
    class_name = "Image-Save-save";
    Separate_Function = true;
    this->path = v[0];
    this->fps = std::stoi(v[1]);
    this->width = std::stoi(v[2]);
    this->height = std::stoi(v[3]);
    index = 0;
    data_type_support.push_back(std::pair<std::vector<uint8_t>, uint8_t>({MAT},UNKNOW));
}

save::save(std::string path, char* video_ptr_head, long size, int fps, int width, int height){
    name = "save";
    class_name = "Image-Save-save";
    Separate_Function = true;
    this->path = path;
    this->video_ptr_head = video_ptr_head;
    this->current_video_ptr = video_ptr_head;
    this->size = size;
    this->fps = fps;
    this->width = width;
    this->height = height;
    index = 0;
    data_type_support.push_back(std::pair<std::vector<uint8_t>, uint8_t>({MAT},UNKNOW));
}

save::save(){
    name = "save";
    class_name = "Image-Save-save";
    Separate_Function = true;
    index = 0;
    data_type_support.push_back(std::pair<std::vector<uint8_t>, uint8_t>({MAT},UNKNOW));
}

save::~save(){

}

void save::registe(){
    Function::Register("Image-Save-save", createObject);
    Function::Register("Image-Save-save", createObject2);
}

Function* save::createObject(std::vector<std::string> params){
    return new save(params);
}

Function* save::createObject2(){
    return new save();
}

void save::start(){
    writer.open(this->path, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), this->fps, cv::Size(this->width, this->height), true);
}

bool save::waitForResource(){
    return true;
}

void save::process(std::vector<std::vector<Data*>>& data_input, std::vector<Data*>& data_output){
    // 验证输入个数
    assert(batch_size != 0);
    assert(data_input.size() <= batch_size);
    assert(data_input[0].size() == 1);
    // 处理
    for(int i = 0; i < data_input.size(); i++){
        if(data_input[i][0] == DATA_END)
            break;
        // 接收Mat
        Data* d = data_input[i][0];
        short app_id = d->getAppId();
        short flow_id = d->getFlowId();
        short request_id = d->getRequestId();
        cv::Mat* src = new cv::Mat(d->context.mat.rows, d->context.mat.cols, CV_8UC3); 
        src->data = d->context.mat.data;
        src->datastart = d->context.mat.data;
        src->dataend = d->context.mat.data + d->context.mat.rows*d->context.mat.cols*d->context.mat.channels;
        src->datalimit = src->dataend;
        // 保存到内存
        memcpy(current_video_ptr, d->context.mat.data, d->context.mat.rows*d->context.mat.cols*d->context.mat.channels);
        current_video_ptr += d->context.mat.rows*d->context.mat.cols*d->context.mat.channels;
        // 释放内存
        if(d->subRefCount() == 0){
            executor->free((char*)(d->context.mat.data));
            executor->free((char*)(d));
        }
        char* ptr = executor->malloc(Data_Memory);
        Data* data = new (ptr)Data(app_id, flow_id, request_id, UNKNOW);
        data_output.push_back(data);
    }
}

bool save::releaseResource(){
    return true;
}

void save::finish(){
    writer.release();
}

bool save::process(){
    if(index >= size){
        return false;
    }else{
        cv::Mat mat(height, width, CV_8UC3);
        mat.data = (uchar*)(current_video_ptr);
        mat.datastart = mat.data;
        mat.dataend = mat.datastart + width*height*3;
        mat.datalimit = mat.dataend;
        writer << mat;
        current_video_ptr += width*height*3;
        std::cout << "save video: " << index << std::endl;
    }
    index++;
    return true;
}

void save::copy(Function* other){
    Function::defaultCopy(other);
    save* oth = dynamic_cast<save*>(other);
    this->path = oth->path;
    this->video_ptr_head = oth->video_ptr_head;
    this->current_video_ptr = oth->video_ptr_head;
    this->size = oth->size;
    this->fps = oth->fps;
    this->width = oth->width;
    this->height = oth->height;
}

};